package wxapp

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"huling/utils/results"
	utils "huling/utils/tool"
	"io/ioutil"
	"os"
	"regexp"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
)

// 获取登录openid-并且添加数据
func GetOpenId(context *gin.Context) {
	code := context.DefaultQuery("code", "")
	ref := Get("https://api.weixin.qq.com/sns/jscode2session?appid=wx01dfc71d22c516e1&secret=84734afc6b754f64735ac1db618f7e70&js_code=" + code + "&grant_type=authorization_code")
	var parameter map[string]interface{}
	if err := json.Unmarshal([]byte(ref), &parameter); err == nil {
		user, _ := DB().Table("wxapp_user").Where("openid", parameter["openid"]).Fields("id,accountID,name,avatar,nickname,openid,unionid,isauth").First()
		if user != nil {
			//token
			token := getToken(user)
			results.Success(context, "直接获取已有的用户数据", user, token)
		} else { //不存在则添加一条
			appid := context.DefaultQuery("appid", "")
			account, _ := DB().Table("wxapp_account").Where("appid", appid).Fields("uid,accountID").First()
			parameter["uid"] = account["uid"]
			parameter["accountID"] = account["accountID"]
			parameter["createtime"] = time.Now().Unix()
			parameter["avatar"] = "resource/staticfile/logo.png"
			addId, err := DB().Table("wxapp_user").Data(parameter).InsertGetId()
			if err != nil {
				results.Failed(context, "添加账号失败", ref)
			} else {
				DB().Table("wxapp_user").Data(map[string]interface{}{"name": fmt.Sprintf("%s%v", "hl_", addId)}).Where("id", addId).Update()
				user, _ := DB().Table("wxapp_user").Where("id", addId).Fields("id,accountID,name,avatar,nickname,openid,unionid,isauth").First()
				//token
				token := getToken(user)
				results.Success(context, "添加并获取token！", user, token)
			}
		}
	} else {
		results.Failed(context, "获取openid失败", err)
	}
}

// 授权完善客户资料
func SaveUser(context *gin.Context) {
	//获取post传过来的data
	body, _ := ioutil.ReadAll(context.Request.Body)
	var parameter map[string]interface{}
	_ = json.Unmarshal(body, &parameter)
	//当前用户
	getuser, _ := context.Get("user")
	user := getuser.(*utils.UserClaims)

	parameter["authtime"] = time.Now().Unix()
	parameter["isauth"] = 1
	parameter["name"] = parameter["nickname"]
	_, err := DB().Table("wxapp_user").
		Data(parameter).
		Where("id", user.ID).
		Update()
	if err != nil {
		results.Failed(context, "完善资料失败", err)
	} else {
		user, _ := DB().Table("wxapp_user").Where("id", user.ID).Fields("id,accountID,name,avatar,nickname,openid,unionid,isauth").First()
		token := getToken(user)
		results.Success(context, "完善资料成功！", user, token)
	}
}

// 获取Token
func getToken(user map[string]interface{}) interface{} {
	token := utils.GenerateToken(&utils.UserClaims{
		ID:             user["id"].(int64),
		Accountid:      user["accountID"].(int64),
		Openid:         user["openid"].(string),
		StandardClaims: jwt.StandardClaims{},
	})
	return token
}

// 获取用户手机
func GetPhone(context *gin.Context) {
	appid := context.DefaultQuery("appid", "")
	code := context.DefaultQuery("code", "")
	account, _ := DB().Table("wxapp_account").Where("appid", appid).Fields("id,access_token,secret,expires_in").First()
	expires_in := account["expires_in"].(int64)
	nowtime := time.Now().Unix()
	if expires_in-nowtime <= 0 {
		access_ref := Get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + account["secret"].(string))
		var access_parameter map[string]interface{}
		if err := json.Unmarshal([]byte(access_ref), &access_parameter); err == nil {
			account["access_token"] = access_parameter["access_token"]
			DB().Table("wxapp_account").Data(access_parameter).Where("id", account["id"]).Update()
		} else {
			results.Failed(context, "获取access_token失败", err)
			return
		}
	}
	ref := Post("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+account["access_token"].(string),
		map[string]interface{}{"code": code}, "application/json")
	var parameter map[string]interface{}
	if err := json.Unmarshal([]byte(ref), &parameter); err == nil {
		if parameter["errmsg"] == "ok" {
			var phone_info map[string]interface{}
			m_phone_info, _ := json.Marshal(parameter["phone_info"])
			json.Unmarshal(m_phone_info, &phone_info)
			//当前用户
			getuser, _ := context.Get("user")
			user := getuser.(*utils.UserClaims)
			_, err := DB().Table("wxapp_user").Data(map[string]interface{}{"mobile": phone_info["phoneNumber"]}).Where("id", user.ID).Update()
			if err == nil {
				results.Success(context, "获取用户手机", "ok", nil)
			} else {
				results.Failed(context, "获取手机失败1", err)
			}
		} else {
			results.Failed(context, "获取手机失败2", parameter)
		}
	} else {
		results.Failed(context, "获取手机失败", err)
	}
}

// 获取小程序码 wxacode
// 请求传参 appid
func GetWxacode(context *gin.Context) {
	//当前用户
	getuser, _ := context.Get("user")
	user := getuser.(*utils.UserClaims)
	appid := context.DefaultQuery("appid", "0")
	tplid := context.DefaultQuery("tplid", "0")
	account, _ := DB().Table("wxapp_account").Where("appid", appid).Fields("id,access_token,secret,expires_in").First()
	expires_in := account["expires_in"].(int64)
	nowtime := time.Now().Unix()
	if expires_in-nowtime <= 0 {
		access_ref := Get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + account["secret"].(string))
		var access_parameter map[string]interface{}
		if err := json.Unmarshal([]byte(access_ref), &access_parameter); err == nil {
			account["access_token"] = access_parameter["access_token"]
			DB().Table("wxapp_account").Data(access_parameter).Where("id", account["id"]).Update()
		} else {
			results.Failed(context, "获取access_token失败", err)
			return
		}
	}
	//获取模板配色
	wxapp_tpl, _ := DB().Table("wxapp_tpl").Where("id", tplid).Fields("line_color_r,line_color_g,line_color_b").First()
	refdata := Postwxa("https://api.weixin.qq.com/wxa/getwxacode?access_token="+account["access_token"].(string),
		map[string]interface{}{"path": fmt.Sprintf("%s%v", "pages/visitcard/visitcard?id=", user.ID), "width": 280, "is_hyaline": true, "auto_color": true,
			"line_color": map[string]interface{}{"r": wxapp_tpl["line_color_r"], "g": wxapp_tpl["line_color_g"], "b": wxapp_tpl["line_color_b"]}}, "application/json")
	if refdata != nil {
		file_path := fmt.Sprintf("%s%s%s", "resource/uploads/", time.Now().Format("20060102"), "/")
		//如果没有filepath文件目录就创建一个
		if _, err := os.Stat(file_path); err != nil {
			if !os.IsExist(err) {
				os.MkdirAll(file_path, os.ModePerm)
			}
		}
		//上传到的路径
		buf := bytes.NewBuffer([]byte(refdata.([]uint8)))
		var base64Encoding string
		base64Encoding = "data:image/png;base64,"
		base64Encoding += base64.StdEncoding.EncodeToString(buf.Bytes()) //生成base64,使用图片base64解码，就可以查看到原图，开始我不懂，直接用base64解码，结果尴尬了
		spath, err := WriteFile(file_path, base64Encoding, user.ID)
		if err == nil {
			DB().Table("wxapp_user").
				Data(map[string]interface{}{"wxacode": spath}).
				Where("id", user.ID).
				Update()
		}
		results.Success(context, "模板切换获取小程序码，并且已经保存", spath, wxapp_tpl)
	}
}

// 首次获取一张第一次进入我的名片
func GetFirstwxaCode(context *gin.Context) {
	getuser, _ := context.Get("user")
	user := getuser.(*utils.UserClaims)
	appid := context.DefaultQuery("appid", "")
	account, _ := DB().Table("wxapp_account").Where("appid", appid).Fields("id,access_token,secret,expires_in").First()
	expires_in := account["expires_in"].(int64)
	nowtime := time.Now().Unix()
	if expires_in-nowtime <= 0 {
		access_ref := Get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + account["secret"].(string))
		var access_parameter map[string]interface{}
		if err := json.Unmarshal([]byte(access_ref), &access_parameter); err == nil {
			account["access_token"] = access_parameter["access_token"]
			DB().Table("wxapp_account").Data(access_parameter).Where("id", account["id"]).Update()
		} else {
			results.Failed(context, "获取access_token失败", err)
			return
		}
	}
	refdata := Postwxa("https://api.weixin.qq.com/wxa/getwxacode?access_token="+account["access_token"].(string),
		map[string]interface{}{"path": fmt.Sprintf("%s%v", "pages/visitcard/visitcard?id=", user.ID), "width": 280, "is_hyaline": true}, "application/json")
	if refdata != nil {
		file_path := fmt.Sprintf("%s%s%s", "resource/uploads/", time.Now().Format("20060102"), "/wxacode/")
		//如果没有filepath文件目录就创建一个
		if _, err := os.Stat(file_path); err != nil {
			if !os.IsExist(err) {
				os.MkdirAll(file_path, os.ModePerm)
			}
		}
		//上传到的路径
		buf := bytes.NewBuffer([]byte(refdata.([]uint8)))
		var base64Encoding string
		base64Encoding = "data:image/png;base64,"
		base64Encoding += base64.StdEncoding.EncodeToString(buf.Bytes()) //生成base64,使用图片base64解码，就可以查看到原图，开始我不懂，直接用base64解码，结果尴尬了
		spath, err := WriteFile(file_path, base64Encoding, user.ID)
		if err == nil {
			DB().Table("wxapp_user").
				Data(map[string]interface{}{"wxacodedf": spath}).
				Where("id", user.ID).
				Update()
		}
		results.Success(context, "获取小程序码，并且已经保存", spath, nil)
	}
}

// 写入文件,保存
func WriteFile(path string, base64_image_content string, UId interface{}) (string, error) {
	b, erro := regexp.MatchString(`^data:\s*image\/(\w+);base64,`, base64_image_content)
	if !b {
		return "格式错误", erro
	}
	re, _ := regexp.Compile(`^data:\s*image\/(\w+);base64,`)
	allData := re.FindAllSubmatch([]byte(base64_image_content), 2)
	fileType := string(allData[0][1]) //png ，jpeg 后缀获取

	base64Str := re.ReplaceAllString(base64_image_content, "")

	var file string = fmt.Sprintf("%s%v%s%s", path, UId, "_wxacode.", fileType)
	byte, _ := base64.StdEncoding.DecodeString(base64Str)
	err := ioutil.WriteFile(file, byte, 0666)
	if err != nil {
		return "", err
	} else {
		return file, nil
	}
}

// 刷新token
func Refreshtoken(context *gin.Context) {
	token := context.Request.Header.Get("Authorization")
	newtoken := utils.Refresh(token)
	results.Success(context, "刷新token", newtoken, nil)
}
